package com.stary.code;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.beetl.sql.core.SQLManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.stary.beetlsql.generator.config.PackageConfig;
import com.stary.beetlsql.generator.config.rules.DBType;
import com.stary.code.springboot.Constants;
import com.stary.code.springboot.config.MavenConfig;
import com.stary.code.springboot.config.SpringBootProjectConfig;
import com.stary.code.springboot.config.TemplateConfig;
import com.stary.code.springboot.config.data.BeetlsqlConfig;
import com.stary.code.springboot.config.data.DataSourceConfig;
import com.stary.code.springboot.config.data.MongodbConfig;
import com.stary.code.springboot.config.data.MybatisPlusConfig;
import com.stary.code.springboot.config.data.RedisConfig;
import com.stary.code.springboot.config.doc.TablesDocConfig;
import com.stary.code.springboot.config.log.LogBackConfig;
import com.stary.code.springboot.config.mq.ActivemqConfig;
import com.stary.code.springboot.config.mq.KafkaConfig;
import com.stary.code.springboot.config.mq.RabbitmqConfig;
import com.stary.code.springboot.config.other.MailConfig;
import com.stary.code.springboot.config.search.ElasticsearchConfig;
import com.stary.code.springboot.config.search.SolrConfig;
import com.stary.code.springboot.rules.DataSourcePoolType;
import com.stary.code.springboot.rules.SimpleDependency;
import com.stary.code.springboot.rules.WebViewType;
import com.stary.code.util.JdbcUtils;
import com.stary.code.util.SqlFileExecutor;

/**
 * <p>生成器</p>
 * @author stary {@link stary1993@qq.com}
 * @date 2018-6-29
 */
public class AutoGenerator {

	private static final Logger logger = LoggerFactory.getLogger(AutoGenerator.class);

	/**
	 * 项目生成根目录
	 */
	private String outDir = "e:\\gen\\";
	/**
	 * 开发人员
	 */
	private String author = "stary";

	/**
	 * 数据源配置
	 */
	private DataSourceConfig dataSource;
	/**
	 * maven配置
	 */
	private MavenConfig maven;
	/**
	 * spring boot配置
	 */
	private SpringBootProjectConfig springBootProject;
	/**
	 * logback配置
	 */
	private LogBackConfig logBack;
	/**
	 * MyBatisPlus代码生成器配置
	 */
	private MybatisPlusConfig mybatisPlus;
	/**
	 * redis配置
	 */
	private RedisConfig redis;
	/**
	 * mongoDB 配置
	 */
	private MongodbConfig mongoDB;
	/**
	 * 邮件配置
	 */
	private MailConfig mail;

	/**
	 * activeMQ配置
	 */
	private ActivemqConfig activeMQ;
	/**
	 * kafka配置
	 */
	private KafkaConfig kafka;
	/**
	 * rabbitMQ配置
	 */
	private RabbitmqConfig rabbitMQ;
	/**
	 * 表文档配置
	 */
	private TablesDocConfig tablesDoc;
	/**
	 * solr配置
	 */
	private SolrConfig solr;
	/**
	 * elasticSearch配置
	 */
	private ElasticsearchConfig elasticsearch;
	/**
	 * beetlsql配置
	 */
	private BeetlsqlConfig beetlsql;

	public ElasticsearchConfig getElasticsearch() {
		return elasticsearch;
	}

	public AutoGenerator setElasticsearch(ElasticsearchConfig elasticsearch) {
		this.elasticsearch = elasticsearch;
		return this;
	}

	public SolrConfig getSolr() {
		return solr;
	}

	public AutoGenerator setSolr(SolrConfig solr) {
		this.solr = solr;
		return this;
	}

	public TablesDocConfig getTablesDoc() {
		return tablesDoc;
	}

	public AutoGenerator setTablesDoc(TablesDocConfig tablesDoc) {
		this.tablesDoc = tablesDoc;
		return this;
	}

	public RabbitmqConfig getRabbitMQ() {
		return rabbitMQ;
	}

	public AutoGenerator setRabbitMQ(RabbitmqConfig rabbitMQ) {
		this.rabbitMQ = rabbitMQ;
		return this;
	}

	public KafkaConfig getKafka() {
		return kafka;
	}

	public AutoGenerator setKafka(KafkaConfig kafka) {
		this.kafka = kafka;
		return this;
	}

	public ActivemqConfig getActiveMQ() {
		return activeMQ;
	}

	public AutoGenerator setActiveMQ(ActivemqConfig activeMQ) {
		this.activeMQ = activeMQ;
		return this;
	}

	public MailConfig getMail() {
		return mail;
	}

	public AutoGenerator setMail(MailConfig mail) {
		this.mail = mail;
		return this;
	}

	public MongodbConfig getMongoDB() {
		return mongoDB;
	}

	public AutoGenerator setMongoDB(MongodbConfig mongoDB) {
		this.mongoDB = mongoDB;
		return this;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public MavenConfig getMaven() {
		if (maven == null) {			
			maven = new MavenConfig();
		}
		return maven;
	}

	public AutoGenerator setMaven(MavenConfig maven) {
		this.maven = maven;
		return this;
	}

	public String getOutDir() {
		return outDir;
	}

	public void setOutDir(String outDir) {
		if (!outDir.endsWith(File.separator)) {
			outDir += File.separator;
		}
		this.outDir = outDir;
	}

	public DataSourceConfig getDataSource() {
		return dataSource;
	}

	public AutoGenerator setDataSource(DataSourceConfig dataSource) {
		this.dataSource = dataSource;
		return this;
	}

	public LogBackConfig getLogBack() {
		if (getSpringBootProject().isOpenLogback()) {
			if (getMaven() == null) {
				throw new RuntimeException("maven config is null");
			}
			if (logBack == null) {
				logBack = new LogBackConfig();
				logBack.setFileName(getMaven().getArtifactId());
			}
		}
		return logBack;
	}

	public AutoGenerator setLogBack(LogBackConfig logBack) {		
		this.logBack = logBack;
		return this;
	}

	public MybatisPlusConfig getMybatisPlus() {				
		return mybatisPlus;
	}

	public AutoGenerator setSpringBootProject(SpringBootProjectConfig springBootProject) {
		this.springBootProject = springBootProject;
		return this;
	}

	public SpringBootProjectConfig getSpringBootProject() {
		if (springBootProject == null) {
			springBootProject = new SpringBootProjectConfig();
		}
		return springBootProject;
	}
	/**
	 * 初始化mybatisPlus配置
	 * @param mybatisPlus
	 * @return
	 */
	public AutoGenerator setMybatisPlus(MybatisPlusConfig mybatisPlus) {
		if (dataSource == null) {
			throw new RuntimeException("data source is null");
		}
		mybatisPlus.setDbUrl(dataSource.getUrl());
		mybatisPlus.setDbUserName(dataSource.getUsername());
		mybatisPlus.setDbPassword(dataSource.getPassword());
		mybatisPlus.setDbType(dataSource.getType());		
		mybatisPlus.setOutputDir(outDir + getMaven().getMainDir());
		mybatisPlus.setPackageName(getMaven().getGroupId() + Constants.POINT + getMaven().getArtifactId());	
		mybatisPlus.setAuthor(author);
		this.mybatisPlus = mybatisPlus;
		return this;
	}
	public BeetlsqlConfig getBeetlsql() {	
		return beetlsql;
	}
	/**
	 * 初始化 beetlsql配置
	 * @param beetlsql
	 * @return
	 */
	public AutoGenerator setBeetlsql(BeetlsqlConfig beetlsql) {
		if (dataSource == null) {
			throw new RuntimeException("data source is null");
		}
		PackageConfig packageInfo = beetlsql.getPackageInfo();
		if (packageInfo == null) {
			packageInfo = new PackageConfig();
		}
		packageInfo.setParent(getMaven().getGroupId() + Constants.POINT + getMaven().getArtifactId());
		beetlsql.setPackageInfo(packageInfo);
		if (beetlsql.getStrategy() == null) {
			beetlsql.setStrategy(new com.stary.beetlsql.generator.config.StrategyConfig());
		}
		DBType dbType = null;
		switch (dataSource.getType()) {
		case MYSQL:
			dbType = DBType.MYSQL;
			break;
		case SQL_SERVER:
			dbType = DBType.SQL_SERVER;
			break;
		default:
			dbType = DBType.ORACLE;
			break;
		}
		com.stary.beetlsql.generator.config.DataSourceConfig beetlsqlDataSource = 
				new com.stary.beetlsql.generator.config.DataSourceConfig();
		beetlsqlDataSource.setDbType(dbType);
		beetlsqlDataSource.setDriverName(dataSource.getDriver());
		beetlsqlDataSource.setUrl(dataSource.getUrl());
		beetlsqlDataSource.setUsername(dataSource.getUsername());
		beetlsqlDataSource.setPassword(dataSource.getPassword());
		beetlsql.setDataSource(beetlsqlDataSource);
		beetlsql.setOutDir(outDir + getMaven().getMainDir().substring(0, getMaven().getMainDir().length() - 1));
		beetlsql.setAuthor(author);
		this.beetlsql = beetlsql;
		return this;
	}

	public RedisConfig getRedis() {
		return redis;
	}

	public AutoGenerator setRedis(RedisConfig redis) {
		this.redis = redis;
		return this;
	}

	/**
	 * 初始化模板配置
	 * @return
	 */
	public TemplateConfig initTemplateConfig(){
		TemplateConfig template = new TemplateConfig();
		logger.debug("---------->> 初始化项目模板参数 <<----------");
		Map<String, Object> paramsMap = new HashMap<>(16);
		paramsMap.put("author", getAuthor());		
		paramsMap.put("mvncfg", getMaven());
		paramsMap.put("sbcfg", getSpringBootProject());
		paramsMap.put("dscfg", getDataSource());		
		paramsMap.put("mpcfg", getMybatisPlus());
		paramsMap.put("lbcfg", getLogBack());		
		paramsMap.put("rcfg", getRedis());
		paramsMap.put("mdcfg", getMongoDB());
		paramsMap.put("mailcfg", getMail());
		paramsMap.put("activemqcfg", getActiveMQ());
		paramsMap.put("rabbitmqcfg", getRabbitMQ());
		paramsMap.put("kafkacfg", getKafka());
		paramsMap.put("solrcfg", getSolr());
		paramsMap.put("escfg", getElasticsearch());
		paramsMap.put("bscfg", getBeetlsql());
		paramsMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));		
		paramsMap.put("app", template.upperCase(getMaven().getArtifactId()) + Constants.APPLICATION);		
		paramsMap.put("sbapp", template.upperCase(getMaven().getArtifactId()) + Constants.SPRING_BOOT_APPLICATION);		
		paramsMap.put("apptests", template.upperCase(getMaven().getArtifactId()) + Constants.APPLICATION_TESTS);		
		if (getSpringBootProject().isOpenDataSource()) {
			if (getSpringBootProject().isTableDocCreated()) {
				if (getDataSource() != null) {
					if (tablesDoc == null) {
						tablesDoc = new TablesDocConfig();
						tablesDoc.setDocName(getMaven().getName());
					}
					if (StringUtils.isEmpty(tablesDoc.getDocName())) {
						tablesDoc.setDocName(getMaven().getName());
					}
					Set<TableInfo> newList = new HashSet<>();
					if (springBootProject.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())) {
						com.baomidou.mybatisplus.generator.config.DataSourceConfig mybatisplusDataSource = 
								new com.baomidou.mybatisplus.generator.config.DataSourceConfig();
						mybatisplusDataSource.setDriverName(getDataSource().getDriver());
						mybatisplusDataSource.setUrl(getDataSource().getUrl());
						mybatisplusDataSource.setUsername(getDataSource().getUsername());
						mybatisplusDataSource.setPassword(getDataSource().getPassword());
						com.baomidou.mybatisplus.generator.config.StrategyConfig strategyConfig = 
								new com.baomidou.mybatisplus.generator.config.StrategyConfig();
						String[] tables = getMybatisPlus().getTables();
						strategyConfig.setInclude(tables);
						// mybatis-plus工具
						ConfigBuilder builder = new ConfigBuilder(null, mybatisplusDataSource, strategyConfig, null, null);
						List<TableInfo> tList = builder.getTableInfoList();
						if (tablesDoc.getTablePrefixs() != null) {
							String[] tablePrefixs = tablesDoc.getTablePrefixs();
							for (TableInfo table : tList) {
								for (int i = 0; i < tablePrefixs.length; i++) {
									String tablePrefix = tablePrefixs[i];
									if (table.getName().startsWith(tablePrefix.toLowerCase()) || table.getName().startsWith(tablePrefix.toUpperCase())) {
										newList.add(table);
									}									
								}
							}
						} else {
							for (TableInfo table : tList) {
								newList.add(table);
							}
						}
						tablesDoc.setTables(newList);
					}
					if (springBootProject.getDependencyMap().containsKey(SimpleDependency.BEETLSQL.getName())) {
						com.baomidou.mybatisplus.generator.config.DataSourceConfig mybatisplusDataSource = 
								new com.baomidou.mybatisplus.generator.config.DataSourceConfig();
						mybatisplusDataSource.setDriverName(getDataSource().getDriver());
						mybatisplusDataSource.setUrl(getDataSource().getUrl());
						mybatisplusDataSource.setUsername(getDataSource().getUsername());
						mybatisplusDataSource.setPassword(getDataSource().getPassword());
						com.baomidou.mybatisplus.generator.config.StrategyConfig strategyConfig = 
								new com.baomidou.mybatisplus.generator.config.StrategyConfig();
						SQLManager sqlManager = getBeetlsql().getDataSource().getSQLManager(getBeetlsql().getStrategy().getNc());
						Set<String> tableList = sqlManager.getMetaDataManager().allTable();
						String[] include = getBeetlsql().getStrategy().getInclude();
						String[] exclude = getBeetlsql().getStrategy().getExclude();
						if (include != null && exclude != null) {
							throw new RuntimeException("Beetlsql include和exclude只能二选一");
						}
						Set<String> genTables = new HashSet<>();
						for (String tableName : tableList) {
							if (getBeetlsql().getDataSource().getDbType().equals(DBType.ORACLE)) {
								tableName = tableName.toUpperCase();
							}
							if (include != null && include.length > 0) {
								for (String tb : include) {
									if (tableName.equals(tb)) {
										genTables.add(tableName);
									}
								}
							} else {
								if (exclude != null && exclude.length > 0) {
									for (String tb : exclude) {
										if (!tableName.equals(tb)) {
											genTables.add(tableName);
										}
									}
								} else {
									genTables.add(tableName);
								}
							}			
						}
						String[] tables = genTables.toArray(new String[] {});
						strategyConfig.setInclude(tables);
						// mybatis-plus工具
						ConfigBuilder builder = new ConfigBuilder(null, mybatisplusDataSource, strategyConfig, null, null);
						List<TableInfo> tList = builder.getTableInfoList();
						if (tablesDoc.getTablePrefixs() != null) {
							String[] tablePrefixs = tablesDoc.getTablePrefixs();
							for (TableInfo table : tList) {
								for (int i = 0; i < tablePrefixs.length; i++) {
									String tablePrefix = tablePrefixs[i];
									if (table.getName().startsWith(tablePrefix.toLowerCase()) || table.getName().startsWith(tablePrefix.toUpperCase())) {
										newList.add(table);
									}									
								}
							}
						} else {
							for (TableInfo table : tList) {
								newList.add(table);
							}
						}
						tablesDoc.setTables(newList);
					}
				}
				paramsMap.put("tablesdoccfg", getTablesDoc());
			}
		}
		template.setParamsMap(paramsMap);	
		logger.debug("---------->> 初始化项目模板文件 <<----------");
		// 设置模板文件		
		Map<String, String> templatesMap = new HashMap<>(16);
		templatesMap.put(Constants.POM, Constants.TEMPLATE_POM);
		templatesMap.put(Constants.APPLICATION, Constants.TEMPLATE_APPLICATION);
		templatesMap.put(Constants.APPLICATION_TESTS, Constants.TEMPLATE_APPLICATION_TESTS);
		if (Constants.WAR.equals(getMaven().getPackaging())) {
			templatesMap.put(Constants.SPRING_BOOT_APPLICATION, Constants.TEMPLATE_SPRING_BOOT_APPLICATION);
		}
		templatesMap.put(Constants.APPLICATION_PRO_DEV, Constants.TEMPLATE_APPLICATION_PRO_DEV);
		templatesMap.put(Constants.APPLICATION_PRO_PROD, Constants.TEMPLATE_APPLICATION_PRO_PROD);
		templatesMap.put(Constants.APPLICATION_PRO, Constants.TEMPLATE_APPLICATION_PRO);
		templatesMap.put(Constants.TEST, maven.MAVEN_TEST_JAVA);
		if (springBootProject.isOpenView()) {
			if (!WebViewType.JSP.equals(springBootProject.getViewType())) {
				templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
				if (WebViewType.BEETL.equals(springBootProject.getViewType())) {
					templatesMap.put(Constants.BEETL_TEMPLATE_CONFIG, Constants.TEMPLATE_BEETL_TEMPLATE_CONFIG);
				}
			}else{
				templatesMap.put(Constants.JSP, Constants.TEMPLATE_JSP);
			}
			templatesMap.put(Constants.STATIC, Constants.STATIC);
		}
		if (springBootProject.isOpenDataSource()) {
			if (dataSource == null) {
				throw new RuntimeException("data source is null");
			}
			// druid 使用druid-spring-boot-starter，不需要自己配置
			if (DataSourcePoolType.DRUID.equals(dataSource.getPoolType())) {
				springBootProject.getDependencyMap().put(SimpleDependency.DRUID.getName(), SimpleDependency.DRUID.getCode());
			}
			if (springBootProject.isTableDocCreated()) {
				templatesMap.put(Constants.TABLE_DOC, Constants.TEMPLATE_TABLE_DOC);
			}
			// mybatisplus
			if (springBootProject.getDependencyMap() != null 
					&& springBootProject.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())) {
				templatesMap.put(Constants.MY_BATIS_PLUS_CONFIG, Constants.TEMPLATE_MY_BATIS_PLUS_CONFIG);
			}
			// beetlsql
			if (springBootProject.getDependencyMap() != null 
					&& springBootProject.getDependencyMap().containsKey(SimpleDependency.BEETLSQL.getName())) {
				templatesMap.put(Constants.BEETLSQL_CONFIG, Constants.TEMPLATE_BEETLSQL_CONFIG);
				// 默认连接池为HikariCP
				dataSource.setPoolType(DataSourcePoolType.HIKARICP);
			}
		}
		// logback
		if (springBootProject.isOpenLogback()) {
			templatesMap.put(Constants.LOGBACK_SPRING, Constants.TEMPLATE_LOGBACK_SPRING);
		}	
		if (springBootProject.getDependencyMap() != null) {
			// redis
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.REDIS.getName())) {
				templatesMap.put(Constants.REDIS_CONFIG, Constants.TEMPLATE_REDIS_CONFIG);
				templatesMap.put(Constants.REDIS_SERVICE, Constants.TEMPLATE_REDIS_SERVICE);
				templatesMap.put(Constants.REDIS_SERVICE_IMPL, Constants.TEMPLATE_REDIS_SERVICE_IMPL);
			}
			// mongoDB
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.MONGODB.getName())) {
				templatesMap.put(Constants.MONGODB_PAGE, Constants.TEMPLATE_MONGODB_PAGE);
				templatesMap.put(Constants.MONGODB_SERVICE, Constants.TEMPLATE_MONGODB_SERVICE);
				templatesMap.put(Constants.MONGODB_SERVICE_IMPL, Constants.TEMPLATE_MONGODB_SERVICE_IMPL);
				templatesMap.put(Constants.MONGODB_REFLECTIONUTILS, Constants.TEMPLATE_MONGODB_REFLECTIONUTILS);
			}
			// mail
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.MAIL.getName())) {
				templatesMap.put(Constants.MAIL, Constants.TEMPLATE_MAIL);
				templatesMap.put(Constants.MAIL_SERVICE, Constants.TEMPLATE_MAIL_SERVICE);
				templatesMap.put(Constants.MAIL_SERVICE_IMPL, Constants.TEMPLATE_MAIL_SERVICE_IMPL);
				if (!springBootProject.isOpenView()) {
					templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
					templatesMap.put(Constants.STATIC, Constants.STATIC);
				} else {
					if (WebViewType.JSP.equals(springBootProject.getViewType())) {
						templatesMap.put(Constants.TEMPLATES, Constants.TEMPLATES);
					}
				}
			}
			// shiro
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.SHIRO.getName())) {
				templatesMap.put(Constants.SHIRO_CONFIG, Constants.TEMPLATE_SHIRO_CONFIG);
				templatesMap.put(Constants.SHIRO_REALM, Constants.TEMPLATE_SHIRO_REALM);
				templatesMap.put(Constants.SHIRO_UTILS, Constants.TEMPLATE_SHIRO_UTILS);
				if (!springBootProject.getDependencyMap().containsKey(SimpleDependency.REDIS.getName())) {
					templatesMap.put(Constants.EHCACHE_SHIRO, Constants.TEMPLATE_EHCACHE_SHIRO);
				}
				if (springBootProject.isOpenView() && springBootProject.getViewType().equals(WebViewType.FREEMARKER.getName())) {
					templatesMap.put(Constants.SHIRO_TAG_FREEMARKER_CONFIG, Constants.TEMPLATE_SHIRO_TAG_FREEMARKER_CONFIG);
				}
			}
			// schedule
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.SCHEDULE.getName())) {
				templatesMap.put(Constants.SCHEDULE_CONFIG, Constants.TEMPLATE_SCHEDULE_CONFIG);
				templatesMap.put(Constants.SCHEDULE_DYNAMIC_TASK, Constants.TEMPLATE_SCHEDULE_DYNAMIC_TASK);
			}
			// quartz
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.QUARTZ.getName())) {
				if (Constants.SPRINGBOOT_1.equals(springBootProject.getSpringBootVersion().substring(0, 1))) {
					templatesMap.put(Constants.QUARTZ, Constants.TEMPLATE_QUARTZ);
					templatesMap.put(Constants.QUARTZ_CONFIG, Constants.TEMPLATE_QUARTZ_CONFIG);
				}
				templatesMap.put(Constants.QUARTZ_SERVICE, Constants.TEMPLATE_QUARTZ_SERVICE);
				templatesMap.put(Constants.QUARTZ_SERVICE_IMPL, Constants.TEMPLATE_QUARTZ_SERVICE_IMPL);
				templatesMap.put(Constants.QUARTZ_TASKINFO, Constants.TEMPLATE_QUARTZ_TASKINFO);
				templatesMap.put(Constants.QUARTZ_TASKJOB, Constants.TEMPLATE_QUARTZ_TASKJOB);
				if (springBootProject.isOpenDataSource()) {
					if (DbType.ORACLE.equals(dataSource.getType())) {
						templatesMap.put(Constants.QUARTZ_TABLES_ORACLE, Constants.TEMPLATE_QUARTZ_TABLES_ORACLE);
					}
					if(DbType.MYSQL.equals(dataSource.getType())){
						templatesMap.put(Constants.QUARTZ_TABLES_MYSQL, Constants.TEMPLATE_QUARTZ_TABLES_MYSQL);
					}
					if(DbType.SQL_SERVER.equals(dataSource.getType())){
						templatesMap.put(Constants.QUARTZ_TABLES_SQL_SERVER, Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER);
					}
				} else {
					templatesMap.put(Constants.QUARTZ_TABLES_ORACLE, Constants.TEMPLATE_QUARTZ_TABLES_ORACLE);
					templatesMap.put(Constants.QUARTZ_TABLES_MYSQL, Constants.TEMPLATE_QUARTZ_TABLES_MYSQL);
					templatesMap.put(Constants.QUARTZ_TABLES_SQL_SERVER, Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER);
				}
			}
			// activemq
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.ACTIVEMQ.getName())) {
				templatesMap.put(Constants.ACTIVEMQ_CONFIG, Constants.TEMPLATE_ACTIVEMQ_CONFIG);
				templatesMap.put(Constants.ACTIVEMQ_PRODUCER, Constants.TEMPLATE_ACTIVEMQ_PRODUCER);
				templatesMap.put(Constants.ACTIVEMQ_CONSUMER, Constants.TEMPLATE_ACTIVEMQ_CONSUMER);
			}
			// kafka
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.KAFKA.getName())) {
				templatesMap.put(Constants.KAFKA_PRODUCER, Constants.TEMPLATE_KAFKA_PRODUCER);
				templatesMap.put(Constants.KAFKA_CONSUMER, Constants.TEMPLATE_KAFKA_CONSUMER);
			}
			// rabbitmq
			if (springBootProject.getDependencyMap().containsKey(SimpleDependency.RABBITMQ.getName())) {
				templatesMap.put(Constants.RABBITMQ_CONFIG, Constants.TEMPLATE_RABBITMQ_CONFIG);
				templatesMap.put(Constants.RABBITMQ_DIRECT_PRODUCER, Constants.TEMPLATE_RABBITMQ_DIRECT_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_DIRECT_CONSUMER, Constants.TEMPLATE_RABBITMQ_DIRECT_CONSUMER);
				templatesMap.put(Constants.RABBITMQ_FANOUT_PRODUCER, Constants.TEMPLATE_RABBITMQ_FANOUT_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_FANOUT_CONSUMER_1, Constants.TEMPLATE_RABBITMQ_FANOUT_CONSUMER_1);
				templatesMap.put(Constants.RABBITMQ_FANOUT_CONSUMER_2, Constants.TEMPLATE_RABBITMQ_FANOUT_CONSUMER_2);
				templatesMap.put(Constants.RABBITMQ_TOPIC_PRODUCER, Constants.TEMPLATE_RABBITMQ_TOPIC_PRODUCER);
				templatesMap.put(Constants.RABBITMQ_TOPIC_CONSUMER, Constants.TEMPLATE_RABBITMQ_TOPIC_CONSUMER);
				templatesMap.put(Constants.RABBITMQ_TOPIC_CONSUMERS, Constants.TEMPLATE_RABBITMQ_TOPIC_CONSUMERS);
			}
		}
		template.setTemplatesMap(templatesMap);
		return template;
	}

	/**
	 * 执行
	 * @throws Exception 
	 */
	public void excute() throws Exception {
		logger.debug("---------->> 开始生成项目... <<----------");
		TemplateConfig templateConfig = initTemplateConfig();
		Map<String, String> templatesMap = templateConfig.getTemplatesMap();
		Connection conn = null;
		if (springBootProject.isOpenDataSource()) {	
			logger.debug("---------->> 初始化数据源 <<----------");
			try {
				conn = JdbcUtils.getConnection(
						dataSource.getDriver(), dataSource.getUrl(),
						dataSource.getUsername(), dataSource.getPassword());
			} catch (ClassNotFoundException | SQLException e) {
				logger.error(e.getMessage());
			}
			if (conn == null) {
				throw new RuntimeException("invalid data source!");
			} 
		}
		for (Map.Entry<String, String> entry : templatesMap.entrySet()) {
			//String fileName = entry.getKey();
			String templateName = entry.getValue();			
			String outFile = templateConfig.getOutFile(getMaven(), templateName);
			if (StringUtils.isEmpty(outFile)) {
				continue;
			}
			File file = new File(outDir, outFile);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if (!templateName.contains(Constants.POINT)) {
				if (!file.exists()) {
					file.mkdirs();									
				}
			} else {
				if (!file.exists()) {
					file.createNewFile(); 
				}
				Template template = templateConfig.getTemplate(templateName);
				FileOutputStream fos = new FileOutputStream(file); 
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, Constants.UTF8)); 
				template.merge(templateConfig.getVelocityContext(), writer); 
				writer.close(); 
				fos.close();
			}	
			logger.debug("---------->> 成功生成项目文件：{}",(outDir + outFile));
		}
		// 生成 quartz tables
		if (springBootProject.isOpenDataSource()) {
			if (conn == null) {
				throw new RuntimeException("invalid data source!");
			} else {
				if (springBootProject.getDependencyMap() != null 
						&& springBootProject.getDependencyMap().containsKey(SimpleDependency.QUARTZ.getName())) {
					String defaultDbType = Constants.TEMPLATE_QUARTZ_TABLES_ORACLE;
					if (templateConfig.getTemplatesMap().containsKey(Constants.QUARTZ_TABLES_MYSQL)) {
						defaultDbType = Constants.TEMPLATE_QUARTZ_TABLES_MYSQL;
					} else if (templateConfig.getTemplatesMap().containsKey(Constants.QUARTZ_TABLES_SQL_SERVER)) {
						defaultDbType = Constants.TEMPLATE_QUARTZ_TABLES_SQL_SERVER;
					}
					String sqlFile = defaultDbType.substring(1) + Constants.VM_SUFFIX;
					try {
						SqlFileExecutor.execute(conn, sqlFile);
					} catch (Exception e) {						
						logger.error("execute quartz table fail", e);
					}
				}
				JdbcUtils.closeConnection(conn);
			}
			// 生成 mybatis-plus
			if (springBootProject.getDependencyMap() != null && 
					springBootProject.getDependencyMap().containsKey(SimpleDependency.MYBATIS_PLUS.getName())) {
				logger.debug("---------->> mybatis-plus代码生成器启动 ... <<----------");				
				mybatisPlus.execute();					
			}
			// 生成 beetlsql
			if (springBootProject.getDependencyMap() != null && 
					springBootProject.getDependencyMap().containsKey(SimpleDependency.BEETLSQL.getName())) {
				logger.debug("---------->> beetlsql代码生成器启动 ... <<----------");				
				beetlsql.execute();					
			}
		}
		logger.debug("---------->> 所有项目生成完成！！！<<----------");
	}

}